/*
 * Copyright (C) 2007-2011 Geometer Plus <contact@geometerplus.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package org.geometerplus.zlibrary.ui.android.view;

import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.GradientDrawable;
import android.view.*;
import android.util.AttributeSet;
import android.util.Log;

import org.geometerplus.android.fbreader.RLog;
import org.geometerplus.zlibrary.core.view.ZLView;
import org.geometerplus.zlibrary.core.view.ZLViewWidget;
import org.geometerplus.zlibrary.core.application.ZLApplication;

import org.geometerplus.zlibrary.ui.android.library.ZLAndroidActivity;

public class FBAndroidWidget extends View implements ZLViewWidget, View.OnLongClickListener {
	
	private static final String TAG = "FBAndroidWidget";
	private static final boolean DEBUG = true;
	private final Paint myPaint = new Paint();
	private final FBBitmapManager myBitmapManager = new FBBitmapManager(this);
	private Bitmap myFooterBitmap;
	
	 private int mWidth = 480;
	 private int mHeight = 800;
	 private int mCornerX = 0; //拖拽点对应的页脚
	 private int mCornerY = 0;
	 private Path mPath0;
	 private Path mPath1;
	 Bitmap mCurPageBitmap = null; //当前页
	 Bitmap mCurPageBackBitmap = null;
	 Bitmap mNextPageBitmap = null;

	 PointF mTouch = new PointF(); // 拖拽点
	 PointF mBezierStart1 = new PointF(); //贝塞尔曲线起始点
	 PointF mBezierControl1 = new PointF(); //贝塞尔曲线控制点
	 PointF mBeziervertex1 = new PointF(); //贝塞尔曲线顶点
	 PointF mBezierEnd1 = new PointF(); //贝塞尔曲线结束点

	 PointF mBezierStart2 = new PointF(); //另一条贝塞尔曲线
	 PointF mBezierControl2 = new PointF();
	 PointF mBeziervertex2 = new PointF();
	 PointF mBezierEnd2 = new PointF();

	 float mMiddleX;
	 float mMiddleY;
	 float mDegrees;
	 float mTouchToCornerDis;
	 ColorMatrixColorFilter mColorMatrixFilter;
	 Matrix mMatrix;
	 float[] mMatrixArray = { 0, 0, 0, 0, 0, 0, 0, 0, 1.0f };

	 boolean mIsRTandLB; //是否属于右上左下
	 float mMaxLength = (float) Math.hypot(480, 800);
	 int[] mBackShadowColors;
	 int[] mFrontShadowColors;
	 GradientDrawable mBackShadowDrawableLR;
	 GradientDrawable mBackShadowDrawableRL;
	 GradientDrawable mFolderShadowDrawableLR;
	 GradientDrawable mFolderShadowDrawableRL;

	 GradientDrawable mFrontShadowDrawableHBT;
	 GradientDrawable mFrontShadowDrawableHTB;
	 GradientDrawable mFrontShadowDrawableVLR;
	 GradientDrawable mFrontShadowDrawableVRL;

	 private Bitmap mBitmap;
	 private Canvas mCanvas;
	 private Paint mBitmapPaint;
	 Paint paint;

	 Paint mPaint;
	 
	public FBAndroidWidget(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public FBAndroidWidget(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public FBAndroidWidget(Context context) {
		super(context);
		init();
	}

	private void init() {
		// next line prevent ignoring first onKeyDown DPad event
		// after any dialog was closed
		setFocusableInTouchMode(true);
		setDrawingCacheEnabled(false);
		setOnLongClickListener(this);
		mPath0 = new Path();
		mPath1 = new Path();
		createDrawable();
		//  mCanvas = new Canvas(mBitmap);
		  mBitmapPaint = new Paint(Paint.DITHER_FLAG);

		  paint = new Paint();
		  mPaint = new Paint();
		  mPaint.setStyle(Paint.Style.FILL);

		 /* mCurPageBitmap = BitmapFactory.decodeResource(this.getResources(),
		    R.drawable.page1);
		  mNextPageBitmap = BitmapFactory.decodeResource(this.getResources(),
		    R.drawable.page2);*/

		  ColorMatrix cm = new ColorMatrix();
		  float array[] = { 0.55f, 0, 0, 0, 80.0f, 0, 0.55f, 0, 0, 80.0f, 0, 0,
		    0.55f, 0, 80.0f, 0, 0, 0, 0.2f, 0 };
		  cm.set(array);
		  mColorMatrixFilter = new ColorMatrixColorFilter(cm);

		  mMatrix = new Matrix();
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		getAnimationProvider().terminate();
		if (myScreenIsTouched) {
			final ZLView view = ZLApplication.Instance().getCurrentView();
			myScreenIsTouched = false;
			view.onScrollingFinished(ZLView.PageIndex.current);
		}
	}

	@Override
	protected void onDraw(final Canvas canvas) {
		final Context context = getContext();
		if (context instanceof ZLAndroidActivity) {
			((ZLAndroidActivity)context).createWakeLock();
		} else {
			System.err.println("A surprise: view's context is not a ZLAndroidActivity");
		}
		super.onDraw(canvas);

//		final int w = getWidth();
//		final int h = getMainAreaHeight();

		if (getAnimationProvider().inProgress()) {
			onDrawInScrolling(canvas);
		} else {
			onDrawStatic(canvas);
			ZLApplication.Instance().onRepaintFinished();
		}
	}

	private AnimationProvider myAnimationProvider;
	private ZLView.Animation myAnimationType;
	private AnimationProvider getAnimationProvider() {
		final ZLView.Animation type = ZLApplication.Instance().getCurrentView().getAnimationType();
		if (myAnimationProvider == null || myAnimationType != type) {
			myAnimationType = type;
		/*	switch (type) {
				case none:
					myAnimationProvider = new NoneAnimationProvider(myBitmapManager);
					break;
				case curl:
					myAnimationProvider = new CurlAnimationProvider(myBitmapManager);
					break;
				case slide:
					myAnimationProvider = new SlideAnimationProvider(myBitmapManager);
					break;
				case shift:
					myAnimationProvider = new ShiftAnimationProvider(myBitmapManager);
					break;
			}*/
		}
		return myAnimationProvider;
	}

	private void onDrawInScrolling(Canvas canvas) {
		RLog.v("ZLAndroidWidget","onDrawInScrolling");
		final ZLView view = ZLApplication.Instance().getCurrentView();

//		final int w = getWidth();
//		final int h = getMainAreaHeight();

		final AnimationProvider animator = getAnimationProvider();
		final AnimationProvider.Mode oldMode = animator.getMode();
		animator.doStep();
		if (animator.inProgress()) {
			animator.draw(canvas);
			if (animator.getMode().Auto) {
				postInvalidate();
			}
			drawFooter(canvas);
		} else {
			switch (oldMode) {
				case AnimatedScrollingForward:
				{
					final ZLView.PageIndex index = animator.getPageToScrollTo();
					myBitmapManager.shift(index == ZLView.PageIndex.next);
					view.onScrollingFinished(index);
					ZLApplication.Instance().onRepaintFinished();
					break;
				}
				case AnimatedScrollingBackward:
					view.onScrollingFinished(ZLView.PageIndex.current);
					break;
			}
			onDrawStatic(canvas);
		}
	}

	public void reset() {
		myBitmapManager.reset();
	}

	public void repaint() {
		RLog.v("ZLAndroidWidget","@@@@@@@@@@@@@repaint");
		postInvalidate();
	}

	public void startManualScrolling(int x, int y, ZLView.Direction direction) {
		final AnimationProvider animator = getAnimationProvider();
		animator.setup(direction, getWidth(), getMainAreaHeight());
		animator.startManualScrolling(x, y);
	}

	public void scrollManuallyTo(int x, int y) {
		RLog.v("ZLAndroidWidget","scrollManuallyTo");
		final ZLView view = ZLApplication.Instance().getCurrentView();
		final AnimationProvider animator = getAnimationProvider();
		if (view.canScroll(animator.getPageToScrollTo(x, y))) {
			animator.scrollTo(x, y);
			postInvalidate();
		}
	}

	public void startAnimatedScrolling(ZLView.PageIndex pageIndex, int x, int y, ZLView.Direction direction, int speed) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (pageIndex == ZLView.PageIndex.current || !view.canScroll(pageIndex)) {
			return;
		}
		final AnimationProvider animator = getAnimationProvider();
		animator.setup(direction, getWidth(), getMainAreaHeight());
		animator.startAnimatedScrolling(pageIndex, x, y, speed);
		if (animator.getMode().Auto) {
			postInvalidate();
		}
	}

	public void startAnimatedScrolling(ZLView.PageIndex pageIndex, ZLView.Direction direction, int speed) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (pageIndex == ZLView.PageIndex.current || !view.canScroll(pageIndex)) {
			return;
		}
		final AnimationProvider animator = getAnimationProvider();
		animator.setup(direction, getWidth(), getMainAreaHeight());
		animator.startAnimatedScrolling(pageIndex, null, null, speed);
		if (animator.getMode().Auto) {
			postInvalidate();
		}
	}

	public void startAnimatedScrolling(int x, int y, int speed) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		final AnimationProvider animator = getAnimationProvider();
		if (!view.canScroll(animator.getPageToScrollTo(x, y))) {
			animator.terminate();
			return;
		}
		animator.startAnimatedScrolling(x, y, speed);
		postInvalidate();
	}

	void drawOnBitmap(Bitmap bitmap, ZLView.PageIndex index) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (view == null) {
			return;
		}

		final ZLAndroidPaintContext context = new ZLAndroidPaintContext(
			new Canvas(bitmap),
			getWidth(),
			getMainAreaHeight(),
			view.isScrollbarShown() ? getVerticalScrollbarWidth() : 0
		);
		view.paint(context, index);
	}
	
	/**
	 * draw main  view footer info
	 * @param canvas
	 */
	private void drawFooter(Canvas canvas) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		final ZLView.FooterArea footer = view.getFooterArea();

		if (footer == null) {
			myFooterBitmap = null;
			return;
		}

		if (myFooterBitmap != null &&
			(myFooterBitmap.getWidth() != getWidth() ||
			 myFooterBitmap.getHeight() != footer.getHeight())) {
			myFooterBitmap = null;
		}
		if (myFooterBitmap == null) {
			myFooterBitmap = Bitmap.createBitmap(getWidth(), footer.getHeight(), Bitmap.Config.RGB_565);
		}
		final ZLAndroidPaintContext context = new ZLAndroidPaintContext(
			new Canvas(myFooterBitmap),
			getWidth(),
			footer.getHeight(),
			view.isScrollbarShown() ? getVerticalScrollbarWidth() : 0
		);
		footer.paint(context);
		canvas.drawBitmap(myFooterBitmap, 0, getHeight() - footer.getHeight(), myPaint);
	}

	private void onDrawStatic(Canvas canvas) {
		RLog.v("FBAndroidWidget","onDrawStatic");
		myBitmapManager.setSize(getWidth(), getMainAreaHeight());
		//canvas.drawBitmap(myBitmapManager.getBitmap(ZLView.PageIndex.current), 0, 0, myPaint);
		  
		drawCurrentPageArea(canvas, myBitmapManager.getBitmap(ZLView.PageIndex.current), mPath0);
		//drawFooter(canvas);
	}

	@Override
	public boolean onTrackballEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			onKeyDown(KeyEvent.KEYCODE_DPAD_CENTER, null);
		} else {
			ZLApplication.Instance().getCurrentView().onTrackballRotated((int)(10 * event.getX()), (int)(10 * event.getY()));
		}
		return true;
	}


	private class LongClickRunnable implements Runnable {
		public void run() {
			if (performLongClick()) {
				myLongClickPerformed = true;
			}
		}
	}
	private volatile LongClickRunnable myPendingLongClickRunnable;
	private volatile boolean myLongClickPerformed;

	private void postLongClickRunnable() {
        myLongClickPerformed = false;
		myPendingPress = false;
        if (myPendingLongClickRunnable == null) {
            myPendingLongClickRunnable = new LongClickRunnable();
        }
        postDelayed(myPendingLongClickRunnable, 2 * ViewConfiguration.getLongPressTimeout());
    }

	private class ShortClickRunnable implements Runnable {
		public void run() {
			final ZLView view = ZLApplication.Instance().getCurrentView();
			view.onFingerSingleTap(myPressedX, myPressedY);
			myPendingPress = false;
			myPendingShortClickRunnable = null;
		}
	}
	private volatile ShortClickRunnable myPendingShortClickRunnable;

	private volatile boolean myPendingPress;
	private volatile boolean myPendingDoubleTap;
	private int myPressedX, myPressedY;
	private boolean myScreenIsTouched;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		RLog.v("ZLAndroidWidget","onTouchEvent:");
		int x = (int)event.getX();
		int y = (int)event.getY();

		final ZLView view = ZLApplication.Instance().getCurrentView();
		switch (event.getAction()) {
			case MotionEvent.ACTION_UP:
				if (myPendingDoubleTap) {
					view.onFingerDoubleTap(x, y);
				} if (myLongClickPerformed) {
					view.onFingerReleaseAfterLongPress(x, y);
				} else {
					if (myPendingLongClickRunnable != null) {
						removeCallbacks(myPendingLongClickRunnable);
						myPendingLongClickRunnable = null;
					}
					if (myPendingPress) {
						if (view.isDoubleTapSupported()) {
        					if (myPendingShortClickRunnable == null) {
            					myPendingShortClickRunnable = new ShortClickRunnable();
        					}
        					postDelayed(myPendingShortClickRunnable, ViewConfiguration.getDoubleTapTimeout());
						} else {
							view.onFingerSingleTap(x, y);
						}
					} else {
						view.onFingerRelease(x, y);
					}
				}
				myPendingDoubleTap = false;
				myPendingPress = false;
				myScreenIsTouched = false;
				break;
			case MotionEvent.ACTION_DOWN:
				if (myPendingShortClickRunnable != null) {
					removeCallbacks(myPendingShortClickRunnable);
					myPendingShortClickRunnable = null;
					myPendingDoubleTap = true;
				} else {
					postLongClickRunnable();
					myPendingPress = true;
				}
				myScreenIsTouched = true;
				myPressedX = x;
				myPressedY = y;
				break;
			case MotionEvent.ACTION_MOVE:
			{
				final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
				final boolean isAMove =
					Math.abs(myPressedX - x) > slop || Math.abs(myPressedY - y) > slop;
				if (isAMove) {
					myPendingDoubleTap = false;
				}
				if (myLongClickPerformed) {
					view.onFingerMoveAfterLongPress(x, y);
				} else {
					if (myPendingPress) {
						if (isAMove) {
							if (myPendingShortClickRunnable != null) {
								removeCallbacks(myPendingShortClickRunnable);
								myPendingShortClickRunnable = null;
							}
							if (myPendingLongClickRunnable != null) {
								removeCallbacks(myPendingLongClickRunnable);
							}
							view.onFingerPress(myPressedX, myPressedY);
							myPendingPress = false;
						}
					}
					if (!myPendingPress) {
						view.onFingerMove(x, y);
					}
				}
				break;
			}
		}

		return true;
	}

	public boolean onLongClick(View v) {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		return view.onFingerLongPress(myPressedX, myPressedY);
	}

	private int myKeyUnderTracking = -1;
	private long myTrackingStartTime;

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		final ZLApplication application = ZLApplication.Instance();

		if (application.hasActionForKey(keyCode, true) ||
			application.hasActionForKey(keyCode, false)) {
			if (myKeyUnderTracking != -1) {
				if (myKeyUnderTracking == keyCode) {
					return true;
				} else {
					myKeyUnderTracking = -1;
				}
			}
			if (application.hasActionForKey(keyCode, true)) {
				myKeyUnderTracking = keyCode;
				myTrackingStartTime = System.currentTimeMillis();
				return true;
			} else {
				return application.doActionByKey(keyCode, false);
			}
		} else {
			return false;
		}
	}

	public boolean onKeyUp(int keyCode, KeyEvent event) {
		if (myKeyUnderTracking != -1) {
			if (myKeyUnderTracking == keyCode) {
				final boolean longPress = System.currentTimeMillis() >
					myTrackingStartTime + ViewConfiguration.getLongPressTimeout();
				ZLApplication.Instance().doActionByKey(keyCode, longPress);
			}
			myKeyUnderTracking = -1;
			return true;
		} else {
			final ZLApplication application = ZLApplication.Instance();
			return
				application.hasActionForKey(keyCode, false) ||
				application.hasActionForKey(keyCode, true);
		}
	}

	protected int computeVerticalScrollExtent() {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (!view.isScrollbarShown()) {
			return 0;
		}
		final AnimationProvider animator = getAnimationProvider();
		if (animator.inProgress()) {
			final int from = view.getScrollbarThumbLength(ZLView.PageIndex.current);
			final int to = view.getScrollbarThumbLength(animator.getPageToScrollTo());
			final int percent = animator.getScrolledPercent();
			return (from * (100 - percent) + to * percent) / 100;
		} else {
			return view.getScrollbarThumbLength(ZLView.PageIndex.current);
		}
	}

	protected int computeVerticalScrollOffset() {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (!view.isScrollbarShown()) {
			return 0;
		}
		final AnimationProvider animator = getAnimationProvider();
		if (animator.inProgress()) {
			final int from = view.getScrollbarThumbPosition(ZLView.PageIndex.current);
			final int to = view.getScrollbarThumbPosition(animator.getPageToScrollTo());
			final int percent = animator.getScrolledPercent();
			return (from * (100 - percent) + to * percent) / 100;
		} else {
			return view.getScrollbarThumbPosition(ZLView.PageIndex.current);
		}
	}

	protected int computeVerticalScrollRange() {
		final ZLView view = ZLApplication.Instance().getCurrentView();
		if (!view.isScrollbarShown()) {
			return 0;
		}
		return view.getScrollbarFullSize();
	}

	private int getMainAreaHeight() {
		final ZLView.FooterArea footer = ZLApplication.Instance().getCurrentView().getFooterArea();
		return footer != null ? getHeight() - footer.getHeight() : getHeight();
	}
	
	 /**
	  * 计算拖拽点对应的拖拽脚
	  */
	 private void calcCornerXY(float x, float y) {
	  if (x <= mWidth / 2)
	   mCornerX = 0;
	  else
	   mCornerX = mWidth;
	  if (y <= mHeight / 2)
	   mCornerY = 0;
	  else
	   mCornerY = mHeight;
	  if ((mCornerX == 0 && mCornerY == mHeight)
	    || (mCornerX == mWidth && mCornerY == 0))
	   mIsRTandLB = true;
	  else
	   mIsRTandLB = false;
	 }
	
	 /**
	  * 求解直线P1P2和直线P3P4的交点坐标
	  */
	 public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {
	  PointF CrossP = new PointF();
	  // 二元函数通式： y=ax+b
	  float a1 = (P2.y - P1.y) / (P2.x - P1.x);
	  float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x);

	  float a2 = (P4.y - P3.y) / (P4.x - P3.x);
	  float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);
	  CrossP.x = (b2 - b1) / (a1 - a2);
	  CrossP.y = a1 * CrossP.x + b1;
	  return CrossP;
	 }

	 private void calcPoints() {
	  mMiddleX = (mTouch.x + mCornerX) / 2;
	  mMiddleY = (mTouch.y + mCornerY) / 2;
	  mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
	    * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
	  mBezierControl1.y = mCornerY;
	  mBezierControl2.x = mCornerX;
	  mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
	    * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);

	  Log.i(TAG, "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);
	  Log.i(TAG, "mBezierControl1.x  " + mBezierControl1.x
	    + "  mBezierControl1.y  " + mBezierControl1.y);
	  Log.i(TAG, "mBezierControl2.x  " + mBezierControl2.x
	    + "  mBezierControl2.y  " + mBezierControl2.y);

	  mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)
	    / 2;
	  mBezierStart1.y = mCornerY;

	  // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时
	  // 如果继续翻页，会出现BUG故在此限制
	  if (mBezierStart1.x < 0 || mBezierStart1.x > 480) {   
	   if (mBezierStart1.x < 0)         
	    mBezierStart1.x = mWidth - mBezierStart1.x;

	   float f1 = Math.abs(mCornerX - mTouch.x);
	   float f2 = mWidth * f1 / mBezierStart1.x;
	   mTouch.x = Math.abs(mCornerX - f2);

	   float f3 = Math.abs(mCornerX - mTouch.x)
	     * Math.abs(mCornerY - mTouch.y) / f1;
	   mTouch.y = Math.abs(mCornerY - f3);
	   mMiddleX = (mTouch.x + mCornerX) / 2;
	   mMiddleY = (mTouch.y + mCornerY) / 2;

	   mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
	     * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
	   mBezierControl1.y = mCornerY;

	   mBezierControl2.x = mCornerX;
	   mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
	     * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
	   Log.i(TAG, "mTouchX --> " + mTouch.x + "  mTouchY-->  "
	     + mTouch.y);
	   Log.i(TAG, "mBezierControl1.x--  " + mBezierControl1.x
	     + "  mBezierControl1.y -- " + mBezierControl1.y);
	   Log.i(TAG, "mBezierControl2.x -- " + mBezierControl2.x
	     + "  mBezierControl2.y -- " + mBezierControl2.y);
	   mBezierStart1.x = mBezierControl1.x
	     - (mCornerX - mBezierControl1.x) / 2;
	  }

	  mBezierStart2.x = mCornerX;
	  mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)
	    / 2;

	  mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),
	    (mTouch.y - mCornerY));

	  mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,
	    mBezierStart2);
	  mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,
	    mBezierStart2);

	  Log.i(TAG, "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "
	    + mBezierEnd1.y);
	  Log.i(TAG, "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "
	    + mBezierEnd2.y);

	  /*
	   * mBeziervertex1.x 推导
	   * ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于
	   * (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4
	   */
	  mBeziervertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;
	  mBeziervertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;
	  mBeziervertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;
	  mBeziervertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;
	 }

	 private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {
	  mPath0.reset();
	  mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);
	  mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,
	    mBezierEnd1.y);
	  mPath0.lineTo(mTouch.x, mTouch.y);
	  mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);
	  mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,
	    mBezierStart2.y);
	  mPath0.lineTo(mCornerX, mCornerY);
	  mPath0.close();

	  canvas.save();
	  canvas.clipPath(path, Region.Op.XOR);
	  canvas.drawBitmap(bitmap, 0, 0, null);
	  canvas.restore();
	 }

	 private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {
	  mPath1.reset();
	  mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);
	  mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
	  mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);
	  mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
	  mPath1.lineTo(mCornerX, mCornerY);
	  mPath1.close();

	  mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x
	    - mCornerX, mBezierControl2.y - mCornerY));
	  int leftx;
	  int rightx;
	  GradientDrawable mBackShadowDrawable;
	  if (mIsRTandLB) {
	   leftx = (int) (mBezierStart1.x);
	   rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);
	   mBackShadowDrawable = mBackShadowDrawableLR;
	  } else {
	   leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);
	   rightx = (int) mBezierStart1.x;
	   mBackShadowDrawable = mBackShadowDrawableRL;
	  }
	  canvas.save();
	  canvas.clipPath(mPath0);
	  canvas.clipPath(mPath1, Region.Op.INTERSECT);
	  canvas.drawBitmap(bitmap, 0, 0, null);
	  canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
	  mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,
	    (int) (mMaxLength + mBezierStart1.y));
	  mBackShadowDrawable.draw(canvas);
	  canvas.restore();
	 }
	 
	 /**
	  *创建阴影的GradientDrawable
	  */
	 private void createDrawable() {
	  int[] color = { 0x333333, 0xb0333333 };
	  mFolderShadowDrawableRL = new GradientDrawable(
	    GradientDrawable.Orientation.RIGHT_LEFT, color);
	  mFolderShadowDrawableRL
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mFolderShadowDrawableLR = new GradientDrawable(
	    GradientDrawable.Orientation.LEFT_RIGHT, color);
	  mFolderShadowDrawableLR
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mBackShadowColors = new int[] { 0xff111111, 0x111111 };
	  mBackShadowDrawableRL = new GradientDrawable(
	    GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);
	  mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mBackShadowDrawableLR = new GradientDrawable(
	    GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);
	  mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mFrontShadowColors = new int[] { 0x80111111, 0x111111 };
	  mFrontShadowDrawableVLR = new GradientDrawable(
	    GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);
	  mFrontShadowDrawableVLR
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);
	  mFrontShadowDrawableVRL = new GradientDrawable(
	    GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);
	  mFrontShadowDrawableVRL
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mFrontShadowDrawableHTB = new GradientDrawable(
	    GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);
	  mFrontShadowDrawableHTB
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);

	  mFrontShadowDrawableHBT = new GradientDrawable(
	    GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);
	  mFrontShadowDrawableHBT
	    .setGradientType(GradientDrawable.LINEAR_GRADIENT);
	 }

	 /**
	  * 绘制翻起页的阴影
	  */
	 public void drawCurrentPageShadow(Canvas canvas) {
	  double degree;
	  if (mIsRTandLB) {
	   degree = Math.PI
	     / 4
	     - Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x
	       - mBezierControl1.x);
	  } else {
	   degree = Math.PI
	     / 4
	     - Math.atan2(mTouch.y - mBezierControl1.y, mTouch.x
	       - mBezierControl1.x);
	  }
	  //翻起页阴影顶点与touch点的距离
	  double d1 = (float) 25 * 1.414 * Math.cos(degree);
	  double d2 = (float) 25 * 1.414 * Math.sin(degree);
	  float x = (float) (mTouch.x + d1);
	  float y;
	  if (mIsRTandLB) {
	   y = (float) (mTouch.y + d2);   
	  } else {
	   y = (float) (mTouch.y - d2);
	  }
	  mPath1.reset();
	  mPath1.moveTo(x, y);
	  mPath1.lineTo(mTouch.x, mTouch.y);
	  mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);
	  mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);
	  mPath1.close();
	  float rotateDegrees;
	  canvas.save();

	  canvas.clipPath(mPath0, Region.Op.XOR);
	  canvas.clipPath(mPath1, Region.Op.INTERSECT);
	  int leftx;
	  int rightx;
	  GradientDrawable mCurrentPageShadow;
	  if (mIsRTandLB) {
	   leftx = (int) (mBezierControl1.x);
	   rightx = (int) mBezierControl1.x + 25;
	   mCurrentPageShadow = mFrontShadowDrawableVLR;
	  } else {
	   leftx = (int) (mBezierControl1.x - 25);
	   rightx = (int) mBezierControl1.x + 1;
	   mCurrentPageShadow = mFrontShadowDrawableVRL;
	  }

	  rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouch.x
	    - mBezierControl1.x, mBezierControl1.y - mTouch.y));
	  canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);
	  mCurrentPageShadow.setBounds(leftx,
	    (int) (mBezierControl1.y - mMaxLength), rightx,
	    (int) (mBezierControl1.y));
	  mCurrentPageShadow.draw(canvas);
	  canvas.restore();

	  mPath1.reset();
	  mPath1.moveTo(x, y);
	  mPath1.lineTo(mTouch.x, mTouch.y);
	  mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);
	  mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
	  mPath1.close();
	  canvas.save();
	  canvas.clipPath(mPath0, Region.Op.XOR);
	  canvas.clipPath(mPath1, Region.Op.INTERSECT);
	  if (mIsRTandLB) {
	   leftx = (int) (mBezierControl2.y);
	   rightx = (int) (mBezierControl2.y + 25);
	   mCurrentPageShadow = mFrontShadowDrawableHTB;
	  } else {
	   leftx = (int) (mBezierControl2.y - 25);
	   rightx = (int) (mBezierControl2.y + 1);
	   mCurrentPageShadow = mFrontShadowDrawableHBT;
	  }
	  rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y
	    - mTouch.y, mBezierControl2.x - mTouch.x));
	  canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
	  float temp;
	  if (mBezierControl2.y < 0)
	   temp = mBezierControl2.y - 800;
	  else
	   temp = mBezierControl2.y;

	  int hmg = (int) Math.hypot(mBezierControl2.x, temp);
	  if (hmg > mMaxLength)
	   mCurrentPageShadow
	     .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,
	       (int) (mBezierControl2.x + mMaxLength) - hmg,
	       rightx);
	  else
	   mCurrentPageShadow.setBounds(
	     (int) (mBezierControl2.x - mMaxLength), leftx,
	     (int) (mBezierControl2.x), rightx);

	  Log.i(TAG, "mBezierControl2.x   " + mBezierControl2.x
	    + "  mBezierControl2.y  " + mBezierControl2.y);
	  mCurrentPageShadow.draw(canvas);
	  canvas.restore();
	 }

	 /**
	  *  绘制翻起页背面
	  */
	 private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
	  int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;
	  float f1 = Math.abs(i - mBezierControl1.x);
	  int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;
	  float f2 = Math.abs(i1 - mBezierControl2.y);
	  float f3 = Math.min(f1, f2);
	  mPath1.reset();
	  mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);
	  mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
	  mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
	  mPath1.lineTo(mTouch.x, mTouch.y);
	  mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
	  mPath1.close();
	  GradientDrawable mFolderShadowDrawable;
	  int left;
	  int right;
	  if (mIsRTandLB) {
	   left = (int) (mBezierStart1.x - 1);
	   right = (int) (mBezierStart1.x + f3 + 1);
	   mFolderShadowDrawable = mFolderShadowDrawableLR;
	  } else {
	   left= (int) (mBezierStart1.x - f3 - 1);
	   right= (int) (mBezierStart1.x + 1);
	   mFolderShadowDrawable = mFolderShadowDrawableRL;
	  }
	  canvas.save();
	  canvas.clipPath(mPath0);
	  canvas.clipPath(mPath1, Region.Op.INTERSECT);

	  mPaint.setColorFilter(mColorMatrixFilter);

	  float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,
	    mBezierControl2.y - mCornerY);
	  float f8 = (mCornerX - mBezierControl1.x) / dis;
	  float f9 = (mBezierControl2.y - mCornerY) / dis;
	  mMatrixArray[0] = 1 - 2 * f9 * f9;
	  mMatrixArray[1] = 2 * f8 * f9;
	  mMatrixArray[3] = mMatrixArray[1];
	  mMatrixArray[4] = 1 - 2 * f8 * f8;
	  mMatrix.reset();
	  mMatrix.setValues(mMatrixArray);
	  mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);
	  mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
	  canvas.drawBitmap(bitmap, mMatrix, mPaint);
	  mPaint.setColorFilter(null);
	  canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
	  mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,
	    (int) (mBezierStart1.y + mMaxLength));
	  mFolderShadowDrawable.draw(canvas);
	  canvas.restore();
	 }
}
